using System;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Threading.Tasks;
using HengTong.Model.Db;
using HengTong.Model.Db.Hr;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using TiaoTaoHelper.Wtm.Services;
using WalkingTec.Mvvm.Core.Support.Quartz;

namespace HengTong.Tasks;

/// <summary>
/// 更新人员档案年龄、工龄和司龄
/// </summary>
[Display(Name = "自动更新人员档案年龄、工龄和司龄", Description = "自动更新人员档案年龄、工龄和司龄")]
[QuartzRepeat(3600 * 24, 0, true, 60 * 30)] // 每天执行一次，延迟1800秒启动
public class UpdatePersonAgeTask : BaseTask<UpdatePersonAgeTask>
{
    protected override async Task<bool> ExecuteStart()
    {
        try
        {
            var startTime = DateTime.Now;
            Logger.LogInformation($"开始更新人员档案年龄、工龄和司龄 - {startTime:yyyy-MM-dd HH:mm:ss}");

            // 查询需要更新的人员数据
            var personList = await Wtm.DC.Set<SysPerson>()
                .Where(e => !string.IsNullOrEmpty(e.IdCardNo) && e.IdCardNo.Length >= 15)
                .ToListAsync();

            int updateAgeCount = 0;
            int updateWorkYearsCount = 0;
            int updateCompanyYearsCount = 0;

            foreach (var person in personList)
            {
                bool needUpdate = false;

                // 计算年龄
                var calculatedAge = CalculateAgeFromIdCard(person.IdCardNo);
                if (calculatedAge.HasValue && calculatedAge != person.Age)
                {
                    person.Age = calculatedAge.Value;
                    updateAgeCount++;
                    needUpdate = true;
                }

                // 计算工龄
                var calculatedWorkYears = CalculateWorkYears(person.JoinWorkDate);
                if (calculatedWorkYears.HasValue && calculatedWorkYears != person.WorkYears)
                {
                    person.WorkYears = calculatedWorkYears.Value;
                    updateWorkYearsCount++;
                    needUpdate = true;
                }

                // 计算司龄
                var calculatedCompanyYears = CalculateCompanyYears(person.HireDate);
                if (calculatedCompanyYears.HasValue && calculatedCompanyYears != person.CompanyYears)
                {
                    person.CompanyYears = calculatedCompanyYears.Value;
                    updateCompanyYearsCount++;
                    needUpdate = true;
                }

                if (needUpdate)
                {
                    Wtm.DC.Set<SysPerson>().Update(person);
                }
            }

            // 批量保存更改
            await Wtm.DC.SaveChangesAsync();

            var endTime = DateTime.Now;
            var duration = (endTime - startTime).TotalSeconds;

            Logger.LogInformation($"人员档案更新完成 - 执行时间: {duration:F2}秒, " +
                                  $"更新年龄记录数: {updateAgeCount}/{personList.Count}, " +
                                  $"更新工龄记录数: {updateWorkYearsCount}/{personList.Count}, " +
                                  $"更新司龄记录数: {updateCompanyYearsCount}/{personList.Count}");

            return true;
        }
        catch (Exception e)
        {
            Logger.LogError(e, "更新人员档案信息时发生错误");
            return false;
        }
    }

    /// <summary>
    /// 根据身份证号计算年龄
    /// </summary>
    /// <param name="idCardNo">身份证号</param>
    /// <returns>年龄，如果身份证号格式不正确则返回null</returns>
    private int? CalculateAgeFromIdCard(string idCardNo)
    {
        if (string.IsNullOrEmpty(idCardNo))
            return null;

        try
        {
            DateTime birthDate;

            // 处理15位和18位身份证号
            if (idCardNo.Length == 15)
            {
                // 15位身份证，出生年份只有两位，需要补全
                var year = int.Parse("19" + idCardNo.Substring(6, 2));
                var month = int.Parse(idCardNo.Substring(8, 2));
                var day = int.Parse(idCardNo.Substring(10, 2));
                birthDate = new DateTime(year, month, day);
            }
            else if (idCardNo.Length == 18)
            {
                // 18位身份证
                var year = int.Parse(idCardNo.Substring(6, 4));
                var month = int.Parse(idCardNo.Substring(10, 2));
                var day = int.Parse(idCardNo.Substring(12, 2));
                birthDate = new DateTime(year, month, day);
            }
            else
            {
                return null;
            }

            return CalculateYearsDifference(birthDate, DateTime.Today);
        }
        catch (Exception)
        {
            return null;
        }
    }

    /// <summary>
    /// 根据参加工作日期计算工龄
    /// </summary>
    /// <param name="joinWorkDate">参加工作日期</param>
    /// <returns>工龄，如果参加工作日期为null或无效则返回null</returns>
    private decimal? CalculateWorkYears(DateTime? joinWorkDate)
    {
        if (!joinWorkDate.HasValue)
            return null;

        try
        {
            return CalculateYearsDifferenceWithDecimal(joinWorkDate.Value, DateTime.Today);
        }
        catch (Exception)
        {
            return null;
        }
    }

    /// <summary>
    /// 根据入职日期计算司龄
    /// </summary>
    /// <param name="hireDate">入职日期</param>
    /// <returns>司龄，如果入职日期为null或无效则返回null</returns>
    private decimal? CalculateCompanyYears(DateTime? hireDate)
    {
        if (!hireDate.HasValue)
            return null;

        try
        {
            return CalculateYearsDifferenceWithDecimal(hireDate.Value, DateTime.Today);
        }
        catch (Exception)
        {
            return null;
        }
    }

    /// <summary>
    /// 计算两个日期之间的年份差（精确到小数点后一位）
    /// </summary>
    /// <param name="startDate">开始日期</param>
    /// <param name="endDate">结束日期</param>
    /// <returns>年份差（保留一位小数）</returns>
    private decimal? CalculateYearsDifferenceWithDecimal(DateTime startDate, DateTime endDate)
    {
        var totalDays = (endDate - startDate).TotalDays;
        if (totalDays < 0)
            return null;

        // 计算年份，保留一位小数
        var years = (decimal)(totalDays / 365.25); // 365.25考虑闰年
        return Math.Round(years, 1);
    }

    /// <summary>
    /// 计算两个日期之间的年份差（整数）
    /// </summary>
    /// <param name="startDate">开始日期</param>
    /// <param name="endDate">结束日期</param>
    /// <returns>年份差（整数）</returns>
    private int CalculateYearsDifference(DateTime startDate, DateTime endDate)
    {
        var age = endDate.Year - startDate.Year;
        if (endDate.Month < startDate.Month ||
            (endDate.Month == startDate.Month && endDate.Day < startDate.Day))
        {
            age--;
        }

        return age;
    }
}